#include "widgetarecorder.h"
#include "ui_widgetarecorder.h"
#include <QDebug>//打印调试信息
#include <QMessageBox>//消息框
#include <QIntValidator> //限定端口号范围

WidgetARecorder::WidgetARecorder(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::WidgetARecorder)
{
    ui->setupUi(this);
    //指针初始化为空
    m_pSocket = NULL;
    //初始化界面
    InitUI();
}

WidgetARecorder::~WidgetARecorder()
{
    //指针置空
    delete m_pSocket;   m_pSocket = NULL;
    //销毁界面
    delete ui;
}

//初始化界面
void WidgetARecorder::InitUI()
{
    //填充输入设备组合框
    QStringList listDevices = m_aRecorder.audioInputs();
    ui->comboBoxDeviceIn->addItems( listDevices );
    //填充音频编码器组合框
    QStringList listCodecs = m_aRecorder.supportedAudioCodecs();
    ui->comboBoxCodec->addItems( listCodecs );
    ui->comboBoxCodec->setCurrentText( "audio/pcm" ); //默认PCM
    //编码质量
    QStringList listQualities;
    //质量字符串的序号就是质量的枚举数值
    listQualities<<"VeryLow_8k8bit"<<"Low_22k8bit"<<"Normal_44k16bit"
                 <<"High_48k16bit"<<"VeryHigh_96k16bit" ;
    ui->comboBoxQuality->addItems( listQualities );
    //通道数量
    QStringList listChannels;
    listChannels<< "1" << "2" ;
    ui->comboBoxChannelCount->addItems( listChannels );
    //容器格式
    QStringList listContainers = m_aRecorder.supportedContainers();
    ui->comboBoxContainerFormat->addItems( listContainers );
    ui->comboBoxContainerFormat->setCurrentText( "audio/x-wav" ); //默认WAV
    //默认文件路径
    ui->lineEditFile->setText( "E:/ar_8k1c8bit.wav" );
    //默认发送IP
    ui->lineEditIP->setText( "127.0.0.1" );
    //端口
    QIntValidator *vali = new QIntValidator(1, 65535);
    ui->lineEditPort->setValidator( vali );
    ui->lineEditPort->setText( "12345" );//默认端口

    //设置采集探针的数据源
    m_aProbe.setSource( &m_aRecorder );
    //关联信号和槽函数
    connect(&m_aRecorder, SIGNAL(statusChanged(QMediaRecorder::Status)),
            this, SLOT(onStatusChanged(QMediaRecorder::Status)) );
    connect(&m_aRecorder, SIGNAL(error(QMediaRecorder::Error)),
            this, SLOT(onError(QMediaRecorder::Error)) );
    connect(&m_aRecorder, SIGNAL(durationChanged(qint64)),
            this, SLOT(onDurationChanged(qint64)) );
    //实时获取数据的信号和槽
    connect(&m_aProbe, SIGNAL(audioBufferProbed(QAudioBuffer)),
            this, SLOT(onAudioBufferProbed(QAudioBuffer)) );
}

void WidgetARecorder::on_pushButtonStart_clicked()
{
    //网络参数设置
    QHostAddress ipAddr;
    if( ! ipAddr.setAddress( ui->lineEditIP->text() ) )
    {
        QMessageBox::warning(this, tr("IP地址"), tr("IP地址格式不正确！"));
        return;
    }
    //端口
    quint16 nPort = ui->lineEditPort->text().toUShort();
    //套接字
    m_pSocket = new QUdpSocket();
    //连接到目标主机
    m_pSocket->connectToHost( ipAddr, nPort );

    //设置录音参数
    //输入设备
    m_aRecorder.setAudioInput( ui->comboBoxDeviceIn->currentText() );
    //编码器参数
    m_aEncoder.setCodec( ui->comboBoxCodec->currentText() );
    //通道数
    m_aEncoder.setChannelCount( ui->comboBoxChannelCount->currentText().toInt() );
    //固定质量模式
    m_aEncoder.setEncodingMode( QMultimedia::ConstantQualityEncoding );
    //编码质量
    QMultimedia::EncodingQuality  quality = (QMultimedia::EncodingQuality)(ui->comboBoxQuality->currentIndex());
    m_aEncoder.setQuality( quality );
    //将编码器设置给录音对象
    m_aRecorder.setAudioSettings( m_aEncoder );
    //文件容器格式
    m_aRecorder.setContainerFormat( ui->comboBoxContainerFormat->currentText() );
    //保存文件路径
    m_aRecorder.setOutputLocation( QUrl::fromLocalFile( ui->lineEditFile->text() ) );

    //录音对象设置完毕，探针的数据源在初始化函数已经设置好了
    //开始录音
    m_aRecorder.record();

    //开始录音之后，打印保存文件URL
    qDebug()<<m_aRecorder.outputLocation();
    //固定参数
    holdParas(true);
}

//录音时固定参数
void WidgetARecorder::holdParas(bool bHold)
{
    //五个组合框
    ui->comboBoxDeviceIn->setDisabled( bHold );
    ui->comboBoxCodec->setDisabled( bHold );
    ui->comboBoxQuality->setDisabled( bHold );
    ui->comboBoxChannelCount->setDisabled( bHold );
    ui->comboBoxContainerFormat->setDisabled( bHold );
    //三个编辑框
    ui->lineEditFile->setDisabled( bHold );
    ui->lineEditIP->setDisabled( bHold );
    ui->lineEditPort->setDisabled( bHold );
    //开始按钮
    ui->pushButtonStart->setDisabled( bHold );
}

void WidgetARecorder::onStatusChanged(QMediaRecorder::Status status)
{
    qDebug()<<status;
}

void WidgetARecorder::onError(QMediaRecorder::Error error)
{
    qDebug()<<error<<": "<<m_aRecorder.errorString();
}

void WidgetARecorder::onDurationChanged(qint64 duration)
{
    if(duration <=0 ) return; //时间不合法
    //秒数 和 毫秒数
    qint64 nSec = duration / 1000;
    qint64 nMS = duration % 1000;
    QString strStatus = tr("录音时间 %1.%2 s").arg( nSec ).arg( nMS, 3, 10, QChar('0'));
    //显示到状态标签
    ui->labelStatus->setText( strStatus );
}

void WidgetARecorder::onAudioBufferProbed(const QAudioBuffer &buffer)
{
    int nByteCount = buffer.byteCount();
    const char * data = buffer.constData<char>();
    //发送
    if( NULL != m_pSocket )
    {
        m_pSocket->write( data, nByteCount );
    }
}

void WidgetARecorder::on_pushButtonStop_clicked()
{
    //如果没开始，不处理
    if( m_aRecorder.state() == QMediaRecorder::StoppedState )
    {
        return;
    }
    //停止录音
    m_aRecorder.stop();
    //套接字
    if( NULL != m_pSocket )
    {
        m_pSocket->close();
        //删除网络套接字
        delete m_pSocket;   m_pSocket = NULL;
    }

    //恢复控件
    holdParas(false);
    ui->labelStatus->setText( tr("状态显示") );//还原状态标签
}
